/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */
package com.pig4cloud.pig.mt.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pig.mt.common.api.utils.Query;
import com.pig4cloud.pig.mt.entity.WxMsgReplyRule;
import com.pig4cloud.pig.mt.mapper.WxMsgReplyRuleMapper;
import com.pig4cloud.pig.mt.service.WxMsgReplyRuleService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 自动回复规则
 *
 * @author JLM
 * @date 2021-03-05 11:45:09
 */
@Service
public class WxMsgReplyRuleServiceImpl extends ServiceImpl<WxMsgReplyRuleMapper, WxMsgReplyRule> implements WxMsgReplyRuleService {
	@Autowired
	WxMsgReplyRuleMapper msgReplyRuleMapper;

	@Override
	public IPage queryPage(Map<String, Object> params) {
		String matchValue = (String) params.get("matchValue");
		String appid = (String) params.get("appid");
		IPage<WxMsgReplyRule> page = this.page(
				new Query<WxMsgReplyRule>().getPage(params),
				new QueryWrapper<WxMsgReplyRule>()
						.eq(!StringUtils.isEmpty(appid), "appid", appid)
						.or()
						.apply("appid is null or appid = ''")
						.like(!StringUtils.isEmpty(matchValue), "match_value", matchValue)
						.orderByDesc("update_time")
		);

		return page;
	}

	/**
	 * 保存自动回复规则
	 *
	 * @param msgReplyRule
	 */

	@Override
	public boolean save(WxMsgReplyRule msgReplyRule) {
		if (StringUtils.isNotEmpty(msgReplyRule.getRuleId())) {
			msgReplyRuleMapper.updateById(msgReplyRule);
		} else {
			msgReplyRuleMapper.insert(msgReplyRule);
		}
		return false;
	}

	/**
	 * 获取所有的回复规则
	 *
	 * @return
	 */
	@Override
	public List<WxMsgReplyRule> getRules() {
		return msgReplyRuleMapper.selectList(new QueryWrapper<WxMsgReplyRule>().orderByDesc("rule_id"));
	}

	/**
	 * 获取当前时段内所有有效的回复规则
	 *
	 * @return
	 */
	@Override
	public List<WxMsgReplyRule> getValidRules() {
		return msgReplyRuleMapper.selectList(
				new QueryWrapper<WxMsgReplyRule>()
						.eq("status", 1)
						.isNotNull("match_value")
						.ne("match_value", "")
						.orderByDesc("priority"));
	}

	/**
	 * 筛选符合条件的回复规则
	 *
	 * @param appid      公众号appid
	 * @param exactMatch 是否精确匹配
	 * @param keywords   关键词
	 * @return 规则列表
	 */
	@Override
	public List<WxMsgReplyRule> getMatchedRules(String appid, boolean exactMatch, String keywords) {
		Date ds = new Date();

		LocalTime now = LocalTime.now();
		return this.getValidRules().stream()
				.filter(rule -> StringUtils.isEmpty(rule.getAppid()) || appid.equals(rule.getAppid())) // 检测是否是对应公众号的规则，如果appid为空则为通用规则
				.filter(rule -> null == rule.getEffectTimeStart() || rule.getEffectTimeStart().toLocalTime().isBefore(now))// 检测是否在有效时段，effectTimeStart为null则一直有效
				.filter(rule -> null == rule.getEffectTimeEnd() || rule.getEffectTimeEnd().toLocalTime().isAfter(now)) // 检测是否在有效时段，effectTimeEnd为null则一直有效
				.filter(rule -> isMatch(exactMatch || rule.getExactMatch(), rule.getMatchValue().split(","), keywords)) //检测是否符合匹配规则
				.collect(Collectors.toList());
	}

	/**
	 * 检测文字是否匹配规则
	 * 精确匹配时，需关键词与规则词语一致
	 * 非精确匹配时，检测文字需包含任意一个规则词语
	 *
	 * @param exactMatch 是否精确匹配
	 * @param ruleWords  规则列表
	 * @param checkWords 需检测的文字
	 * @return
	 */
	public static boolean isMatch(boolean exactMatch, String[] ruleWords, String checkWords) {
		if (StringUtils.isEmpty(checkWords)) {
			return false;
		}
		for (String words : ruleWords) {
			if (exactMatch && words.equals(checkWords)) {
				return true;//精确匹配，需关键词与规则词语一致
			}
			if (!exactMatch && checkWords.contains(words)) {
				return true;//模糊匹配
			}
		}
		return false;
	}
}
